﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AAGun.cs" company="">
//   
// </copyright>
// <summary>
//   The aa gun.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace RescueRaiders.Models
{
    using System;

    using Microsoft.Xna.Framework;
    using Microsoft.Xna.Framework.Graphics;

    using RescueRaiders.Properties;

    /// <summary>
    /// The aa gun.
    /// </summary>
    internal sealed class AAGun : BaseModel
    {
        /// <summary>
        /// The base rectangle.
        /// </summary>
        private static readonly Rectangle baseRectangle = new Rectangle(0, 0, 44, 59);

        /// <summary>
        /// The gun rectangle.
        /// </summary>
        private static readonly Rectangle gunRectangle = new Rectangle(44, 0, 44, 59);

        /// <summary>
        /// The precision.
        /// </summary>
        private static readonly float precision = Settings.Default.GunMinSpeed * 2;

        /// <summary>
        /// The range.
        /// </summary>
        private static readonly float range = Settings.Default.ViewHeight * 2;

        /// <summary>
        /// The enemy.
        /// </summary>
        private readonly HeliClass enemy;

        /// <summary>
        /// The magazine.
        /// </summary>
        private readonly InfiniteMagazine magazine;

        /// <summary>
        /// The last fire.
        /// </summary>
        private TimeSpan lastFire;

        /// <summary>
        /// Initializes a new instance of the <see cref="AAGun"/> class.
        /// </summary>
        /// <param name="gunTexture">
        /// The gun texture.
        /// </param>
        /// <param name="ammoTexture">
        /// The ammo texture.
        /// </param>
        /// <param name="position">
        /// The position.
        /// </param>
        /// <param name="side">
        /// The side.
        /// </param>
        /// <param name="enemy">
        /// The enemy.
        /// </param>
        public AAGun(Texture2D gunTexture, Texture2D ammoTexture, Vector2 position, Side side, HeliClass enemy)
            : base(gunTexture, position, side)
        {
            Texturedata = new Color[(baseRectangle.Width * baseRectangle.Height)];
            this.enemy = enemy;
            magazine = new InfiniteMagazine(ammoTexture, range);
            frameSize = new Point(44, 59);
            Center = new Vector2(22, 33);
        }

        /// <summary>
        /// The collide.
        /// </summary>
        /// <param name="other">
        /// The other.
        /// </param>
        public override Vector2 Collide(BaseModel other)
        {
            var vector = base.Collide(other);
            return !vector.Equals(Vector2.Zero) ? vector : magazine.Collide(other);
        }

        /// <summary>
        /// The draw.
        /// </summary>
        /// <param name="spriteBatch">
        /// The sprite batch.
        /// </param>
        /// <param name="cameraX">
        /// The camera x.
        /// </param>
        public override void Draw(SpriteBatch spriteBatch, float cameraX)
        {
            var position = new Vector2(Position.X - cameraX, Position.Y);
            spriteBatch.Draw(Texture, position, baseRectangle, Color.White, 0, Center, 1.0f, SpriteEffects.None, 0.6f);
            spriteBatch.Draw(
                Texture, position, gunRectangle, Color.White, Rotation, Center, 1.0f, SpriteEffects.None, 0.55f);
            magazine.Draw(spriteBatch, cameraX);
        }

        /// <summary>
        /// The update.
        /// </summary>
        /// <param name="gameTime">
        /// The game time.
        /// </param>
        public override void Update(GameTime gameTime)
        {
            Texture.GetData(0, gunRectangle, Texturedata, 0, Texturedata.Length);

            // determine if there is an enemy heli in range if it is then change then track the heli
            var aaToHeliVector = enemy.Position - Position;
            if (aaToHeliVector.Length() < range)
            {
                // calculates the target angle to the enemy hellicopter
                var angleToTarget =
                    (float)Math.Round(MathHelper.PiOver2 + Math.Atan2(aaToHeliVector.Y, aaToHeliVector.X), 2);
                var speed = (Rotation - angleToTarget) * Settings.Default.GunMaxSpeed + Settings.Default.GunMinSpeed;
                Rotation = Rotation < angleToTarget ? Rotation + precision : Rotation - speed;
                if (Math.Abs(Rotation - angleToTarget) <= precision &&
                    gameTime.TotalGameTime - lastFire > Settings.Default.GunFireRate)
                {
                    var verticalAngle = Rotation - MathHelper.PiOver2;
                    var direction =
                        Vector2.Normalize(new Vector2((float)Math.Cos(verticalAngle), (float)Math.Sin(verticalAngle)));
                    var barrelPosition = Position + (direction * Center.Y);
                    var emitterPos = new Vector3(enemy.Position - barrelPosition, 0);
                    magazine.Fire(barrelPosition, direction, Rotation, emitterPos);
                    lastFire = gameTime.TotalGameTime;
                }
            }

            magazine.Update(gameTime);
        }
    }
}